<template>
    <div>
        <Modal v-model="visible" title="批量导入" @on-cancel="handleClose">
            <div>
                <slot name="header" />
                <div class="file-select">
                    <Upload
                        class="file-btn"
                        :before-upload="beforeUpload"
                        :accept="accept"
                        :format="format"
                        :action="action"
                    >
                        <Button type="primary">选择文件</Button>
                    </Upload>
                    <div class="file-name">
                        <Input :value="fileName" readonly />
                    </div>
                </div>
                <slot name="footer" />
            </div>
            <div slot="footer">
                <Button
                    type="primary"
                    :loading="loading"
                    @click="handleImport"
                >导入</Button>
                <Button @click="handleClose">取消</Button>
            </div>
        </Modal>
        <Modal v-model="errorVisible" :title="errorTitle" @on-cancel="handleClose">
            <Table
                :data="errorList"
                :max-height="300"
                :columns="errorColumns"
            />
            <div slot="footer">
                <Button
                    type="primary"
                    @click="handleClose"
                >确定</Button>
            </div>
        </Modal>
    </div>
</template>
<script>
import axios from '@/libs/api.request'
import { importUrl } from '@/api/fileManage'

export default {
    props: {
        // 弹窗title
        title: {
            type: String,
            default: '导入模板'
        },
        // 弹窗状态 可用v-model
        value: {
            type: Boolean,
            default: false
        },
        // 自定义上传地址
        action: {
            type: String,
            default: importUrl
        },
        // 文件格式
        format: {
            type: Array,
            default: _ => ['xls', 'xlsx', 'csv']
        },
        // 文件大小  单位：M
        size: {
            type: Number,
            default: 4
        },
        // 刷新方法 有导入成功的数据 弹窗关闭时调用
        refreshMethod: {
            type: Function,
            default: _ => {}
        },
        // 导入的额外参数
        importParams: {
            type: Object,
            default: () => {
                return {}
            }
        }
    },
    data () {
        return {
            loading: false,
            fileName: '',
            visible: false,
            errorVisible: false,
            errorTitle: '',
            errorList: [],
            errorColumns: [
                {
                    title: '错误描述',
                    align: 'center',
                    render (h, params) {
                        return h('div', params.row.msg)
                    }
                }
            ]
        }
    },
    watch: {
        value (v) {
            this.visible = v
        }
    },
    computed: {
        accept () {
            return this.format.map(item => `.${item}`).join(',')
        },
        acceptTips () {
            return this.format.map(item => `*.${item}`).join('，')
        }
    },
    methods: {
        // 导入前拦截
        beforeUpload (file) {
            if (this.checkFileFormat(file) && this.checkFileSize(file)) {
                this.file = file
                this.fileName = file.name
            } else {
                this.file = ''
                this.fileName = ''
            }
            return false
        },
        // 检查文件格式
        checkFileFormat (file) {
            const fileNameList = file.name.split('.')
            const fileFormat = fileNameList[fileNameList.length - 1].toLocaleLowerCase()
            if (this.format.indexOf(fileFormat) < 0) {
                this.$Message.warning(`只支持${this.acceptTips}格式文件`)
                return false
            }
            return true
        },
        // 检查文件大小
        checkFileSize (file) {
            const maxSize = this.size * 1024 * 1024
            if (file.size > maxSize) {
                this.$Message.warning(`文件${file.name}不能超过${this.size}M`)
                return false
            }
            return true
        },
        handleImport () {
            if (!this.file) {
                this.$Message.warning('请选择文件')
                return
            }
            this.loading = true
            const url = this.action
            const data = new FormData()
            data.append('file', this.file)
            axios.request({
                url,
                params: {
                    params: JSON.stringify(this.importParams)
                },
                data,
                method: 'post'
            }).then(res => {
                if (res.data.code === '0000') {
                    const { errorList = [], successNum = 0, failedNum = 0 } = res.data.data
                    this.importSuccess = successNum > 0
                    if (failedNum > 0) {
                        this.openErrorTable({ errorList, successNum, failedNum })
                    } else {
                        this.handleClose()
                        this.$Message.success(`成功导入${successNum}条`)
                    }
                } else {
                    this.$Message.error(res.data.data || '导入失败')
                }
                this.loading = false
            }).catch(err => {
                this.loading = false
                this.$Message.error(`导入异常: ${err}`)
            })
        },
        openErrorTable ({ errorList, successNum, failedNum }) {
            this.visible = false
            this.errorList = errorList.map(item => ({
                msg: item
            }))
            this.errorTitle = `成功导入${successNum}条，失败${failedNum}条`
            this.errorVisible = true
        },
        handleClose () {
            if (this.importSuccess) {
                this.importSuccess = false
                this.$emit('import-success')
            }
            this.errorVisible = false
            this.$emit('input', false)
            this.fileName = ''
            this.file = null
            this.errorList = []
        }
    }
}
</script>
<style lang="less" scoped>
.file-select {
    margin-bottom: 15px;
    .file-btn {
        float: right;
    }
    .file-name {
        margin-right: 100px;
    }
}
</style>
